home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / common / treasure.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  36KB  |  1,261 lines

  1.  
  2. /*
  3.  * static char *rcs_treasure_c =
  4.  *   "$Id: treasure.c,v 1.42 1996/07/24 07:05:02 master Exp master $";
  5.  */
  6.  
  7. /*
  8.     CrossFire, A Multiplayer game for X-windows
  9.  
  10.     Copyright (C) 1992 Frank Tore Johansen
  11.  
  12.     This program is free software; you can redistribute it and/or modify
  13.     it under the terms of the GNU General Public License as published by
  14.     the Free Software Foundation; either version 2 of the License, or
  15.     (at your option) any later version.
  16.  
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.  
  22.     You should have received a copy of the GNU General Public License
  23.     along with this program; if not, write to the Free Software
  24.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  
  26.     The author can be reached via e-mail to frankj@ifi.uio.no.
  27. */
  28.  
  29. #define ALLOWED_COMBINATION
  30.  
  31. /* TREASURE_DEBUG does some checking on the treasurelists after loading.
  32.  * It is useful for finding bugs in the treasures file.  Since it only
  33.  * slows the startup some (and not actual game play), it is by default
  34.  * left on
  35.  */
  36. #define TREASURE_DEBUG
  37.  
  38.  
  39. #include <global.h>
  40. #include <treasure.h>
  41. #include <spellist.h>
  42. #include <funcpoint.h>
  43.  
  44. treasurelist *first_treasurelist;
  45. artifactlist *first_artifactlist;
  46.  
  47. /*
  48.  * Initialize global archtype pointers:
  49.  */
  50.  
  51. void init_archetype_pointers() {
  52.   int prev_warn = warn_archetypes;
  53.   warn_archetypes = 1;
  54.   if (ring_arch == NULL)
  55.     ring_arch = find_archetype("ring");
  56.   if (amulet_arch == NULL)
  57.     amulet_arch = find_archetype("amulet");
  58.   if (staff_arch == NULL)
  59.     staff_arch = find_archetype("staff");
  60.   if (crown_arch == NULL)
  61.     crown_arch = find_archetype("crown");
  62.   warn_archetypes = prev_warn;
  63. }
  64.  
  65. /*
  66.  * Allocate and return the pointer to an empty treasurelist structure.
  67.  */
  68.  
  69. static treasurelist *get_empty_treasurelist() {
  70.   treasurelist *tl = (treasurelist *) malloc(sizeof(treasurelist));
  71.   if(tl==NULL)
  72.     fatal(OUT_OF_MEMORY);
  73.   tl->name=NULL;
  74.   tl->next=NULL;
  75.   tl->items=NULL;
  76.   tl->total_chance=0;
  77.   return tl;
  78. }
  79.  
  80. /*
  81.  * Allocate and return the pointer to an empty treasure structure.
  82.  */
  83.  
  84. static treasure *get_empty_treasure() {
  85.   treasure *t = (treasure *) malloc(sizeof(treasure));
  86.   if(t==NULL)
  87.     fatal(OUT_OF_MEMORY);
  88.   t->item=NULL;
  89.   t->name=NULL;
  90.   t->next=NULL;
  91.   t->next_yes=NULL;
  92.   t->next_no=NULL;
  93.   t->chance=100;
  94.   t->magic=0;
  95.   t->nrof=0;
  96.   return t;
  97. }
  98.  
  99. /*
  100.  * Reads the lib/treasure file from disk, and parses the contents
  101.  * into an internal treasure structure (very linked lists)
  102.  */
  103.  
  104. static treasure *load_treasure(FILE *fp) {
  105.   char buf[MAX_BUF], *cp, variable[MAX_BUF];
  106.   treasure *t=get_empty_treasure();
  107.   int value;
  108.  
  109.   nroftreasures++;
  110.   while(fgets(buf,MAX_BUF,fp)!=NULL) {
  111.     if(*buf=='#')
  112.       continue;
  113.     if((cp=strchr(buf,'\n'))!=NULL)
  114.       *cp='\0';
  115.     cp=buf;
  116.     while(*cp==' ') /* Skip blanks */
  117.       cp++;
  118.     if(sscanf(cp,"arch %s",variable)) {
  119.       if((t->item=find_archetype(variable))==NULL)
  120.         LOG(llevError,"Treasure lacks archetype: %s\n",variable);
  121.     } else if (sscanf(cp, "list %s", variable))
  122.     t->name = add_string(variable);
  123.     else if(sscanf(cp,"chance %d",&value))
  124.       t->chance=(uint8) value;
  125.     else if(sscanf(cp,"nrof %d",&value))
  126.       t->nrof=(uint16) value;
  127.     else if(sscanf(cp,"magic %d",&value))
  128.       t->magic=(uint8) value;
  129.     else if(!strcmp(cp,"yes"))
  130.       t->next_yes=load_treasure(fp);
  131.     else if(!strcmp(cp,"no"))
  132.       t->next_no=load_treasure(fp);
  133.     else if(!strcmp(cp,"end"))
  134.       return t;
  135.     else if(!strcmp(cp,"more")) {
  136.       t->next=load_treasure(fp);
  137.       return t;
  138.     } else
  139.       LOG(llevError,"Unknown treasure-command: '%s', last entry %s\n",cp,t->name);
  140.   }
  141.   LOG(llevError,"treasure lacks 'end'.\n");
  142.   return t;
  143. }
  144.  
  145. #ifdef TREASURE_DEBUG
  146. /* recursived checks the linked list.  Treasurelist is passed only
  147.  * so that the treasure name can be printed out
  148.  */
  149. static void check_treasurelist(treasure *t, treasurelist *tl)
  150. {
  151.     if (t->item==NULL && t->name==NULL)
  152.     LOG(llevError,"Treasurelist %s has element with no name or archetype\n", tl->name);
  153.     if (t->chance>=100 && t->next_yes && (t->next || t->next_no))
  154.     LOG(llevError,"Treasurelist %s has element that has 100% generation, next_yes field as well as next or next_no\n",
  155.         tl->name);
  156.     /* find_treasurelist will print out its own error message */
  157.     if (t->name && strcmp(t->name,"NONE"))
  158.     (void) find_treasurelist(t->name);
  159.     if (t->next) check_treasurelist(t->next, tl);
  160.     if (t->next_yes) check_treasurelist(t->next_yes,tl);
  161.     if (t->next_no) check_treasurelist(t->next_no, tl);
  162. }
  163. #endif
  164.  
  165. /*
  166.  * Opens LIBDIR/treasure and reads all treasure-declarations from it.
  167.  * Each treasure is parsed with the help of load_treasure().
  168.  */
  169.  
  170. void load_treasures() {
  171.   FILE *fp;
  172.   char filename[MAX_BUF], buf[MAX_BUF], name[MAX_BUF];
  173.   treasurelist *previous=NULL;
  174.   treasure *t;
  175.   int comp;
  176.  
  177.   sprintf(filename,"%s/%s",LibDir,Treasures);
  178.   if((fp=open_and_uncompress(filename,0,&comp))==NULL) {
  179.     LOG(llevError,"Can't open treasure file.\n");
  180.     return;
  181.   }
  182.   while(fgets(buf,MAX_BUF,fp)!=NULL) {
  183.     if(*buf=='#')
  184.       continue;
  185.     if(sscanf(buf,"treasureone %s\n",name) || sscanf(buf,"treasure %s\n",name)) {
  186.       treasurelist *tl=get_empty_treasurelist();
  187.       tl->name=add_string(name);
  188.       if(previous==NULL)
  189.         first_treasurelist=tl;
  190.       else
  191.         previous->next=tl;
  192.       previous=tl;
  193.       tl->items=load_treasure(fp);
  194.       /* This is a one of the many items on the list should be generated.
  195.        * Add up the chance total, and check to make sure the yes & no
  196.        * fields of the treasures are not being used.
  197.        */
  198.       if (!strncmp(buf,"treasureone",11)) {
  199.     for (t=tl->items; t!=NULL; t=t->next) {
  200. #ifdef TREASURE_DEBUG
  201.       if (t->next_yes || t->next_no) {
  202.         LOG(llevError,"Treasure %s is one item, but on treasure %s\n",
  203.         tl->name, t->item ? t->item->name : t->name);
  204.         LOG(llevError,"  the next_yes or next_no field is set");
  205.       }
  206. #endif
  207.       tl->total_chance += t->chance;
  208.     }
  209. #if 0
  210.         LOG(llevDebug, "Total chance for list %s is %d\n", tl->name, tl->total_chance);
  211. #endif
  212.       }
  213.     } else
  214.       LOG(llevError,"Treasure-list didn't understand: %s\n",buf);
  215.   }
  216.   close_and_delete(fp, comp);
  217.  
  218. #ifdef TREASURE_DEBUG
  219. /* Perform some checks on how valid the treasure data actually is.
  220.  * verify that list transitions work (ie, the list that it is supposed
  221.  * to transition to exists).  Also, verify that at least the name
  222.  * or archetype is set for each treasure element.
  223.  */
  224.   for (previous=first_treasurelist; previous!=NULL; previous=previous->next)
  225.     check_treasurelist(previous->items, previous);
  226. #endif
  227. }
  228.  
  229. /*
  230.  * Searches for the given treasurelist in the globally linked list
  231.  * of treasurelists which has been built by load_treasures().
  232.  */
  233.  
  234. treasurelist *find_treasurelist(char *name) {
  235.   char *tmp=find_string(name);
  236.   treasurelist *tl;
  237.   if(tmp!=NULL)
  238.     for(tl=first_treasurelist;tl!=NULL;tl=tl->next)
  239.       if(tmp==tl->name)
  240.         return tl;
  241.   LOG(llevError,"Couldn't find treasurelist %s\n",name);
  242.   return NULL;
  243. }
  244.  
  245.  
  246. /*
  247.  * Generates the objects specified by the given treasure.
  248.  * It goes recursively through the rest of the linked list.
  249.  * If there is a certain percental chance for a treasure to be generated,
  250.  * this is taken into consideration.
  251.  * The second argument specifies for which object the treasure is
  252.  * being generated.
  253.  * If flag isn't GT_ENVIRONMENT, monster_check_apply() is called.
  254.  * If flag is GT_INVISIBLE, only invisible objects are generated (ie, only
  255.  * abilities.  This is used by summon spells, thus no summoned monsters
  256.  * start with equipment, but only their abilities).
  257.  */
  258.  
  259.  
  260. void create_all_treasures(treasure *t, object *op, int flag, int difficulty, int tries) {
  261.   object *tmp;
  262.  
  263.  
  264.   if((int)t->chance >= 100 || (RANDOM()%100 + 1) < (int) t->chance) {
  265.     if (t->name) {
  266.     if (strcmp(t->name,"NONE") && difficulty>=t->magic)
  267.       create_treasure(find_treasurelist(t->name), op, flag, difficulty, tries);
  268.     }
  269.     else {
  270.       if(t->item->clone.invisible != 0 || flag != GT_INVISIBLE) {
  271.         tmp=arch_to_object(t->item);
  272.         if(t->nrof&&tmp->nrof<=1)
  273.           tmp->nrof = RANDOM()%((int) t->nrof) + 1;
  274.         fix_generated_item(tmp,op,difficulty,t->magic);
  275.         if(flag != GT_ENVIRONMENT) {
  276.           tmp = insert_ob_in_ob(tmp,op);
  277.           (void) (*monster_check_apply_func)(op,tmp);
  278.         } else {
  279.           tmp->x=op->x,tmp->y=op->y;
  280.           insert_ob_in_map(tmp,op->map);
  281.     }
  282.       }
  283.     }
  284.     if(t->next_yes!=NULL)
  285.       create_all_treasures(t->next_yes,op,flag,difficulty, tries);
  286.   } else
  287.     if(t->next_no!=NULL)
  288.       create_all_treasures(t->next_no,op,flag,difficulty,tries);
  289.   if(t->next!=NULL)
  290.     create_all_treasures(t->next,op,flag,difficulty, tries);
  291. }
  292.  
  293. void create_one_treasure(treasurelist *tl, object *op, int flag, int difficulty,
  294.     int tries)
  295. {
  296.     int value = RANDOM() % tl->total_chance;
  297.     treasure *t;
  298.  
  299.     if (tries++>100) return;
  300.     for (t=tl->items; t!=NULL; t=t->next) {
  301.     value -= t->chance;
  302.     if (value<0) break;
  303.     }
  304.  
  305.     if (!t || value>=0) {
  306.     LOG(llevError, "create_one_treasure: got null object or not able to find treasure\n");
  307.         abort();
  308.     return;
  309.     }
  310.     if (t->name) {
  311.     if (!strcmp(t->name,"NONE")) return;
  312.     if (difficulty>=t->magic)
  313.         create_treasure(find_treasurelist(t->name), op, flag, difficulty, tries);
  314.     else if (t->nrof)
  315.         create_one_treasure(tl, op, flag, difficulty, tries);
  316.     return;
  317.     }
  318.     if(t->item->clone.invisible != 0 || flag != GT_INVISIBLE) {
  319.     object *tmp=arch_to_object(t->item);
  320.         if(t->nrof&&tmp->nrof<=1)
  321.           tmp->nrof = RANDOM()%((int) t->nrof) + 1;
  322.         fix_generated_item(tmp,op,difficulty,t->magic);
  323.         if(flag != GT_ENVIRONMENT) {
  324.           tmp = insert_ob_in_ob(tmp,op);
  325.           (void) (*monster_check_apply_func)(op,tmp);
  326.         } else {
  327.           tmp->x=op->x,tmp->y=op->y;
  328.           insert_ob_in_map(tmp,op->map);
  329.     }
  330.     }
  331. }
  332.  
  333. /* This calls the appropriate treasure creation function.  tries is passed
  334.  * to determine how many list transitions or attempts to create treasure
  335.  * have been made.  It is really in place to prevent infinite loops with
  336.  * list transitions, or so that excessively good treasure will not be
  337.  * created on weak maps, because it will exceed the number of allowed tries
  338.  * to do that.
  339.  */
  340. void create_treasure(treasurelist *t, object *op, int flag, int difficulty,
  341.     int tries)
  342. {
  343.  
  344.     if (tries++>100) return;
  345.     if (t->total_chance) 
  346.     create_one_treasure(t, op, flag,difficulty, tries);
  347.     else
  348.       create_all_treasures(t->items, op, flag, difficulty, tries);
  349. }
  350.  
  351. /* This is similar to the old generate treasure function.  However,
  352.  * it instead takes a treasurelist.  It is really just a wrapper around
  353.  * create_treasure.  We create a dummy object that the treasure gets
  354.  * inserted into, and then return that treausre
  355.  */
  356. object *generate_treasure(treasurelist *t, int difficulty)
  357. {
  358.     object *ob = get_object(), *tmp;
  359.  
  360.     create_treasure(t, ob, 0, difficulty, 0);
  361.  
  362.     /* Don't want to free the object we are about to return */
  363.     tmp = ob->inv;
  364.     if (tmp!=NULL) remove_ob(tmp);
  365.     if (ob->inv) {
  366.         LOG(llevError,"In generate treasure, created multiple objects.\n");
  367.     }
  368.     free_object(ob);
  369.     return tmp;
  370. }
  371.  
  372. /*
  373.  * This is a new way of calculating the chance for an item to have
  374.  * a specific magical bonus.
  375.  * The array has two arguments, the difficulty of the level, and the
  376.  * magical bonus "wanted".
  377.  */
  378.  
  379. static int difftomagic_list[DIFFLEVELS][MAXMAGIC+1] =
  380. {
  381. /*chance of magic    difficulty*/
  382. /* +0  +1 +2 +3 +4 */
  383.   { 95, 2, 2, 1, 0 }, /*1*/
  384.   { 92, 5, 2, 1, 0 }, /*2*/
  385.   { 85,10, 4, 1, 0 }, /*3*/
  386.   { 80,14, 4, 2, 0 }, /*4*/
  387.   { 75,17, 5, 2, 1 }, /*5*/
  388.   { 70,18, 8, 3, 1 }, /*6*/
  389.   { 65,21,10, 3, 1 }, /*7*/
  390.   { 60,22,12, 4, 2 }, /*8*/
  391.   { 55,25,14, 4, 2 }, /*9*/
  392.   { 50,27,16, 5, 2 }, /*10*/
  393.   { 45,28,18, 6, 3 }, /*11*/
  394.   { 42,28,20, 7, 3 }, /*12*/
  395.   { 40,27,21, 8, 4 }, /*13*/
  396.   { 38,25,22,10, 5 }, /*14*/
  397.   { 36,23,23,12, 6 }, /*15*/
  398.   { 33,21,24,14, 8 }, /*16*/
  399.   { 31,19,25,16, 9 }, /*17*/
  400.   { 27,15,30,18,10 }, /*18*/
  401.   { 20,12,30,25,13 }, /*19*/
  402.   { 15,10,28,30,17 }, /*20*/
  403.   { 13, 9,27,28,23 }, /*21*/
  404.   { 10, 8,25,28,29 }, /*22*/
  405.   {  8, 7,23,26,36 }, /*23*/
  406.   {  6, 6,20,22,46 }, /*24*/
  407.   {  4, 5,17,18,56 }, /*25*/
  408.   {  2, 4,12,14,68 }, /*26*/
  409.   {  0, 3, 7,10,80 }, /*27*/
  410.   {  0, 0, 3, 7,90 }, /*28*/
  411.   {  0, 0, 0, 3,97 }, /*29*/
  412.   {  0, 0, 0, 0,100}, /*30*/
  413.   {  0, 0, 0, 0,100}, /*31*/
  414. };
  415.  
  416. /*
  417.  * Based upon the specified difficulty and upon the difftomagic_list array,
  418.  * a random magical bonus is returned.  This is used when determine
  419.  * the magical bonus created on specific maps.
  420.  */
  421.  
  422. int magic_from_difficulty(int difficulty)
  423. {
  424.   int percent,loop;
  425.  
  426.   difficulty--;
  427.   if(difficulty<0)
  428.     difficulty=0;
  429.  
  430.   if (difficulty>=DIFFLEVELS)
  431.     difficulty=DIFFLEVELS-1;
  432.  
  433.   percent = RANDOM()%100;
  434.  
  435.   for(loop=0;loop<(MAXMAGIC+1);++loop) {
  436.     percent -= difftomagic_list[difficulty][loop];
  437.     if (percent<0)
  438.       break;
  439.   }
  440.   if (loop==(MAXMAGIC+1)) {
  441.     LOG(llevError,"Warning, table for difficulty %d bad.\n",difficulty);
  442.     loop=0;
  443.   }
  444. /*  printf("Chose magic %d for difficulty %d\n",loop,difficulty);*/
  445.   return (RANDOM()%3)?loop:-loop;
  446. }
  447.  
  448. /*
  449.  * Sets magical bonus in an object, and recalculates the effect on
  450.  * the armour variable, and the effect on speed of armour.
  451.  * This function doesn't work properly, should add use of archetypes
  452.  * to make it truly absolute.
  453.  */
  454.  
  455. void set_abs_magic(object *op, int magic) {
  456.   if(!magic)
  457.     return;
  458.  
  459.   op->magic=magic;
  460.   if (op->arch) {
  461.     if (op->type == ARMOUR)
  462.       ARMOUR_SPEED(op)=(ARMOUR_SPEED(&op->arch->clone)*(100+magic*10))/100;
  463.     if (op->armour)
  464.       op->armour=op->arch->clone.armour + (op->arch->clone.armour * magic)/20;
  465.     if (magic < 0 && !(RANDOM()%3)) /* You can't just check the weight always */
  466.       magic = (-magic);
  467.     op->weight = (op->arch->clone.weight*(100-magic*10))/100;
  468.   } else {
  469.     if(op->type==ARMOUR)
  470.       ARMOUR_SPEED(op)=(ARMOUR_SPEED(op)*(100+magic*10))/100;
  471.     if(op->armour)
  472.       op->armour+=(op->armour*magic)/20;
  473.     if (magic < 0 && !(RANDOM()%3)) /* You can't just check the weight always */
  474.       magic = (-magic);
  475.     op->weight=(op->weight*(100-magic*10))/100;
  476.   }
  477. }
  478.  
  479. /*
  480.  * Sets a random magical bonus in the given object based upon
  481.  * the given difficulty, and the given max possible bonus.
  482.  */
  483.  
  484. void set_magic(int difficulty,object *op, int max_magic) {
  485.   int i;
  486.   i = magic_from_difficulty(difficulty);
  487.   if(i > max_magic)
  488.     i = max_magic;
  489.   set_abs_magic(op,i);
  490.   if (i < 0)
  491.     SET_FLAG(op, FLAG_CURSED);
  492. }
  493.  
  494. /*
  495.  * Randomly adds one magical ability to the given object.
  496.  */
  497.  
  498. void set_ring_bonus(object *op,int bonus) {
  499.   int r=RANDOM()%(bonus>0?24:10);
  500.   if(op->type==AMULET)
  501.     if(!(RANDOM()%21))
  502.       r=19+RANDOM()%2;
  503.     else if(RANDOM()&2)
  504.       r=9;
  505.     else
  506.       r=10+RANDOM()%9;
  507.   switch(r) {
  508.   case 0:
  509.     if(op->stats.Str)
  510.       return;
  511.     op->stats.Str=bonus;
  512.     break;
  513.   case 1:
  514.     if(op->stats.Int)
  515.       return;
  516.     op->stats.Int=bonus;
  517.     break;
  518.   case 2:
  519.     if(op->stats.Con)
  520.       return;
  521.     op->stats.Con=bonus;
  522.     break;
  523.   case 3:
  524.     if(op->stats.Dex)
  525.       return;
  526.     op->stats.Dex=bonus;
  527.     break;
  528.   case 4:
  529.     if(op->stats.Cha)
  530.       return;
  531.     op->stats.Cha=bonus;
  532.     break;
  533.   case 5:
  534.     if(op->stats.Wis)
  535.       return;
  536.     op->stats.Wis=bonus;
  537.     break;
  538.   case 6:
  539.     if(op->stats.dam)
  540.       return;
  541.     op->stats.dam=bonus;
  542.     break;
  543.   case 7:
  544.     if(op->stats.wc)
  545.       return;
  546.     op->stats.wc=bonus;
  547.     break;
  548.   case 8:
  549.     if(op->stats.food)
  550.       return;
  551.     op->stats.food=bonus; /* hunger/sustenance */
  552.     break;
  553.   case 9:
  554.     if(op->stats.ac)
  555.       return;
  556.     op->stats.ac=bonus;
  557.     break;
  558.   case 10:
  559.     if(bonus==2) { /* Maybe make an artifact of this? */
  560.       op->immune|=AT_PARALYZE;
  561.       op->immune|=AT_SLOW;
  562.       op->stats.exp+=1;
  563.       op->value*=5;
  564.     } else
  565.       op->protected|=AT_PARALYZE;
  566.     break;
  567.   case 11:
  568.     op->protected|=AT_MAGIC;
  569.     op->value*=2;
  570.     break;
  571.   case 12:
  572.     op->protected|=AT_ELECTRICITY;
  573.     break;
  574.   case 13:
  575.     op->protected|=AT_FIRE;
  576.     op->vulnerable|=AT_COLD;
  577.     op->value=(op->value*3)/2;
  578.     break;
  579.   case 14:
  580.     op->protected|=AT_DRAIN;
  581.     break;
  582.   case 15:
  583.     op->protected|=AT_SLOW;
  584.     break;
  585.   case 16:
  586.     op->protected|=AT_COLD;
  587.     op->vulnerable|=AT_FIRE;
  588.     break;
  589.   case 17:
  590.     op->protected|=AT_POISON;
  591.     break;
  592.   case 18:
  593.     op->protected|=AT_FEAR;
  594.     break;
  595.   case 19:
  596.     if(op->type==AMULET) {
  597.       SET_FLAG(op,FLAG_REFL_SPELL);
  598.       op->value*=11;
  599.     } else {
  600.       op->stats.hp=1; /* regenerate hit points */
  601.       op->value*=4;
  602.     }
  603.     break;
  604.   case 20:
  605.     if(op->type==AMULET) {
  606.       SET_FLAG(op,FLAG_REFL_MISSILE);
  607.       op->value*=9;
  608.     } else {
  609.       op->stats.sp=1; /* regenerate spell points */
  610.       op->value*=3;
  611.     }
  612.     break;
  613.   case 21:
  614.     if(op->stats.exp)
  615.       return;
  616.     op->stats.exp=bonus; /* Speed! */
  617.     op->value=(op->value*2)/3;
  618.     break;
  619.   }
  620.   if(bonus>0)
  621.     op->value*=2*bonus;
  622.   else
  623.     op->value= -(op->value*2*bonus)/3;
  624. }
  625.  
  626. /*
  627.  * get_magic(diff) will return a random number between 0 and 4.
  628.  * diff can be any value above 2.  The higher the diff-variable, the
  629.  * higher is the chance of returning a low number.
  630.  * It is only used in fix_generated_treasure() to set bonuses on
  631.  * rings and amulets.
  632.  * Another scheme is used to calculate the magic of weapons and armours.
  633.  */
  634.  
  635. int get_magic(int diff) {
  636.   int i;
  637.   if(diff<3)
  638.     diff=3;
  639.   for(i=0;i<4;i++)
  640.     if(RANDOM()%diff) return i;
  641.   return 4;
  642. }
  643.  
  644. #define DICE2    (get_magic(2)==2?2:1)
  645. #define DICESPELL (RANDOM()%3+RANDOM()%3+RANDOM()%3+RANDOM()%3+RANDOM()%3)
  646.  
  647. /*
  648.  * fix_generated_item():  This is called after an item is generated, in
  649.  * order to set it up right.  This produced magical bonuses, puts spells
  650.  * into scrolls/books/wands, makes it unidentified, hides the value, etc.
  651.  */
  652. /* 4/28/96 added creator object from which op may now inherit properties based on
  653.  * op->type. Right now, which stuff the creator passes on is object type 
  654.  * dependant. I know this is a spagetti manuever, but is there a cleaner 
  655.  * way to do this? b.t. */
  656.  
  657. void fix_generated_item(object *op,object *creator,int difficulty, int max_magic) {
  658.   int was_magic = op->magic;
  659.  
  660.   if(!creator||creator->type==op->type) creator=op; /*safety & to prevent polymorphed 
  661.                              * objects giving attributes */ 
  662.  
  663.   if (difficulty<1) difficulty=1;
  664.   if (op->arch == crown_arch) {
  665.     set_magic(difficulty>25?30:difficulty+5, op, max_magic);
  666.     generate_artifact(op,difficulty);
  667.   } else {
  668.     if(!op->magic && max_magic)
  669.       set_magic(difficulty,op,max_magic);
  670.     if ((!was_magic && !(RANDOM()%CHANCE_FOR_ARTIFACT)) || op->type == HORN)
  671.       generate_artifact(op, difficulty);
  672.   }
  673.   if (!op->title) /* Only modify object if not special */
  674.     switch(op->type) {
  675.     case WEAPON:
  676.     case ARMOUR:
  677.     case SHIELD:
  678.     case HELMET:
  679.     case CLOAK:
  680.       if (QUERY_FLAG(op, FLAG_CURSED) && !(RANDOM()%4))
  681.         set_ring_bonus(op, -DICE2);
  682.       break;
  683.     case BRACERS:
  684.       if(!(RANDOM()%(QUERY_FLAG(op, FLAG_CURSED)?5:20))) {
  685.         set_ring_bonus(op,QUERY_FLAG(op, FLAG_CURSED)?-DICE2:DICE2);
  686.         if (!QUERY_FLAG(op, FLAG_CURSED))
  687.           op->value*=3;
  688.       }
  689.       break;
  690.     case AMULET:
  691.       if(op->arch==amulet_arch)
  692.         op->value*=5; /* Since it's not just decoration */
  693.     case RING:
  694.       if(op->arch==NULL) {
  695.         remove_ob(op);
  696.         free_object(op);
  697.         op=NULL;
  698.         break;
  699.       }
  700.       if(op->arch!=ring_arch&&op->arch!=amulet_arch) /* It's a special artefact!*/
  701.         break;
  702.       if(!(RANDOM()%3))
  703.         SET_FLAG(op, FLAG_CURSED);
  704.       set_ring_bonus(op,QUERY_FLAG(op, FLAG_CURSED)?-DICE2:DICE2);
  705.       if(op->type!=RING) /* Amulets have only one ability */
  706.         break;
  707.       if(!(RANDOM()%4)) {
  708.         int d=(RANDOM()%2 || QUERY_FLAG(op, FLAG_CURSED))?-DICE2:DICE2;
  709.         if(d>0)
  710.           op->value*=3;
  711.         set_ring_bonus(op,d);
  712.         if(!(RANDOM()%4)) {
  713.           int d=(RANDOM()%3 || QUERY_FLAG(op, FLAG_CURSED))?-DICE2:DICE2;
  714.           if(d>0)
  715.             op->value*=5;
  716.           set_ring_bonus(op,d);
  717.         }
  718.       }
  719.       if(op->arch->animations)
  720.         op->face=&new_faces[op->arch->faces
  721.         [RANDOM()%((int) op->arch->animations)]];
  722.       break;
  723.     case BOOK:
  724.       /* Is it an empty book?, if yes lets make a special 
  725.        * msg for it, and tailor its properties based on the 
  726.        * creator and/or map level we found it on.
  727.        */
  728.       if(!op->msg&&RANDOM()%10) { 
  729.     /* set the book level properly */
  730.     if(creator->level==0 || QUERY_FLAG(creator,FLAG_ALIVE))
  731.             if(op->map&&op->map->difficulty) 
  732.           op->level=RANDOM()%(op->map->difficulty)+RANDOM()%10+1;
  733.             else
  734.           op->level=RANDOM()%20+1;
  735.     else 
  736.         op->level=RANDOM()%creator->level;
  737.  
  738.     tailor_readable_ob(op,(creator&&creator->stats.sp)?creator->stats.sp:-1);
  739.         /* books w/ info are worth more! */
  740.           op->value*=((op->level>10?op->level:op->level/3)*((strlen(op->msg)/100)+1));
  741.     /* creator related stuff */
  742.     if(QUERY_FLAG(creator,FLAG_NO_PICK)) /* for library, chained books! */
  743.         SET_FLAG(op,FLAG_NO_PICK);
  744.     if(creator->slaying&&!op->slaying) /* for check_inv floors */
  745.         op->slaying = add_string(creator->slaying);
  746. #ifdef ALLOW_SKILLS /* add exp so reading it gives xp (once)*/
  747.         op->stats.exp = op->value/5;
  748. #endif
  749.       }
  750.       break;
  751.     case SPELLBOOK:
  752.       if(!strcmp(op->arch->name,"cleric_book")) 
  753.      do { 
  754.          do
  755.                op->stats.sp=RANDOM()%NROFREALSPELLS;
  756.          while(RANDOM()%10>=spells[op->stats.sp].books); 
  757.      } while (!spells[op->stats.sp].cleric);
  758.       else
  759.      do {
  760.              do   
  761.                op->stats.sp=RANDOM()%NROFREALSPELLS;
  762.              while(RANDOM()%10>=spells[op->stats.sp].books); 
  763.          } while (spells[op->stats.sp].cleric);
  764.  
  765.       op->value=(op->value*spells[op->stats.sp].level)/
  766.                  (spells[op->stats.sp].level+4);
  767.       change_book_name(op);
  768. #ifdef ALLOW_SKILLS /* add exp so learning gives xp */
  769.       op->level = spells[op->stats.sp].level;
  770.       op->stats.exp = op->value;
  771. #endif
  772.       break;
  773.     case WAND:
  774.       do 
  775.         op->stats.sp=RANDOM()%NROFREALSPELLS;
  776.       while (!spells[op->stats.sp].charges||
  777.              spells[op->stats.sp].level>DICESPELL);
  778.       if (spells[op->stats.sp].cleric)
  779.       { /* Make the wand into a staff */
  780.         short i = op->stats.sp;
  781.         if (staff_arch == NULL)
  782.           staff_arch = find_archetype("staff");
  783.         copy_object(&staff_arch->clone, op);
  784.         op->stats.sp = i;
  785.       }
  786.       op->stats.food=RANDOM()%spells[op->stats.sp].charges+1;
  787.       op->level = spells[op->stats.sp].level/2+ RANDOM()%difficulty + RANDOM()%difficulty;
  788.       if (op->level<1) op->level=1;
  789.       op->value=(op->value*spells[op->stats.sp].level)/
  790.                  (spells[op->stats.sp].level+4);
  791.       break;
  792.     case ROD:
  793.       if (op->stats.maxhp)
  794.         op->stats.maxhp += RANDOM()%op->stats.maxhp;
  795.       op->stats.hp = op->stats.maxhp;
  796.       do
  797.         op->stats.sp = RANDOM()%NROFREALSPELLS;
  798.       while (!spells[op->stats.sp].charges||
  799.              spells[op->stats.sp].sp > op->stats.maxhp ||
  800.              spells[op->stats.sp].level>DICESPELL);
  801.       op->level = spells[op->stats.sp].level/2+ RANDOM()%difficulty + RANDOM()%difficulty;
  802.       op->value=(op->value*op->stats.hp*spells[op->stats.sp].level)/
  803.                 (spells[op->stats.sp].level+4);
  804.       break;
  805.     case SCROLL:
  806.       do
  807.         op->stats.sp=RANDOM()%NROFREALSPELLS;
  808.       while (!spells[op->stats.sp].scrolls||
  809.              spells[op->stats.sp].scroll_chance<=RANDOM()%10);
  810.       op->nrof=RANDOM()%spells[op->stats.sp].scrolls+1;
  811.       op->level = spells[op->stats.sp].level/2+ RANDOM()%difficulty +
  812.      RANDOM()%difficulty;
  813.       if (op->level<1) op->level=1;
  814.       op->value=(op->value*spells[op->stats.sp].level)/
  815.                  (spells[op->stats.sp].level+4);
  816. #ifdef ALLOW_SKILLS /* add exp so reading them properly gives xp */ 
  817.       op->stats.exp = op->value/5;
  818. #endif
  819.       break;
  820.     case RUNE:
  821.       (*trap_adjust_func)(op,difficulty);
  822.       break;
  823.     }
  824.   if (op->type == POTION) {
  825.     op->face = potion_face;
  826.     free_string(op->name);
  827.     op->name = add_string("potion");
  828.     op->level = spells[op->stats.sp].level/2+ RANDOM()%difficulty + RANDOM()%difficulty;
  829.     if (RANDOM()%2)
  830.       SET_FLAG(op, FLAG_CURSED);
  831.   }
  832. #if 0
  833.   if (op->arch == NULL)
  834.     LOG(llevDebug, "fix_generated_item(%s) had no arch.\n", op->name);
  835.   else
  836.     op->value = op->arch->clone.value / 2;
  837. #endif
  838. }
  839.  
  840. /*
  841.  *
  842.  *
  843.  * CODE DEALING WITH ARTIFACTS STARTS HERE
  844.  *
  845.  *
  846.  */
  847.  
  848. /*
  849.  * Allocate and return the pointer to an empty artifactlist structure.
  850.  */
  851.  
  852. static artifactlist *get_empty_artifactlist() {
  853.   artifactlist *tl = (artifactlist *) malloc(sizeof(artifactlist));
  854.   if(tl==NULL)
  855.     fatal(OUT_OF_MEMORY);
  856.   tl->next=NULL;
  857.   tl->items=NULL;
  858.   tl->total_chance=0;
  859.   return tl;
  860. }
  861.  
  862. /*
  863.  * Allocate and return the pointer to an empty artifact structure.
  864.  */
  865.  
  866. static artifact *get_empty_artifact() {
  867.   artifact *t = (artifact *) malloc(sizeof(artifact));
  868.   if(t==NULL)
  869.     fatal(OUT_OF_MEMORY);
  870.   t->item=NULL;
  871.   t->next=NULL;
  872.   t->chance=0;
  873.   t->difficulty=0;
  874.   t->allowed = NULL;
  875.   return t;
  876. }
  877.  
  878. /*
  879.  * Searches the artifact lists and returns one that has the same type
  880.  * of objects on it.
  881.  */
  882.  
  883. artifactlist *find_artifactlist(int type) {
  884.   artifactlist *al;
  885.  
  886.   for (al=first_artifactlist; al!=NULL; al=al->next)
  887.     if (al->type == type) return al;
  888.   return NULL;
  889. }
  890.  
  891. /*
  892.  * For debugging purposes.  Dumps all tables.
  893.  */
  894.  
  895. void dump_artifacts() {
  896.   artifactlist *al;
  897.   artifact *art;
  898.   linked_char *next;
  899.  
  900.   fprintf(logfile,"\n");
  901.   for (al=first_artifactlist; al!=NULL; al=al->next) {
  902.     fprintf(logfile, "Artifact has type %d, total_chance=%d\n", al->type, al->total_chance);
  903.     for (art=al->items; art!=NULL; art=art->next) {
  904.       fprintf(logfile,"Artifact %-30s Difficulty %3d Chance %5d\n",
  905.     art->item->name, art->difficulty, art->chance);
  906.       if (art->allowed !=NULL) {
  907.     fprintf(logfile,"\tAllowed combinations:");
  908.     for (next=art->allowed; next!=NULL; next=next->next)
  909.        fprintf(logfile, "%s,", next->name);
  910.     fprintf(logfile,"\n");
  911.       }
  912.     }
  913.   }
  914.   fprintf(logfile,"\n");
  915. }
  916.  
  917.  
  918. /*
  919.  * Builds up the lists of artifacts from the file in the libdir.
  920.  */
  921.  
  922. void init_artifacts() {
  923.   static int has_been_inited=0;
  924.   FILE *fp;
  925.   char filename[MAX_BUF], buf[MAX_BUF], *cp, *next;
  926.   artifact *art=NULL;
  927.   linked_char *tmp;
  928.   int value, comp;
  929.   artifactlist *al;
  930.  
  931.   if (has_been_inited) return;
  932.   else has_been_inited = 1;
  933.  
  934.   LOG(llevDebug, "Reading artifacts...");
  935.   sprintf(filename, "%s/artifacts", LibDir);
  936.   if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
  937.     LOG(llevError, "Can't open %s.\n", filename);
  938.     return;
  939.   }
  940.  
  941.   while (fgets(buf, MAX_BUF, fp)!=NULL) {
  942.     if (*buf=='#') continue;
  943.     if((cp=strchr(buf,'\n'))!=NULL)
  944.       *cp='\0';
  945.     cp=buf;
  946.     while(*cp==' ') /* Skip blanks */
  947.       cp++;
  948.  
  949.     if (!strncmp(cp, "Allowed", 7)) {
  950.       art=get_empty_artifact();
  951.  
  952.       nrofartifacts++;
  953.       cp = strchr(cp,' ') + 1;
  954.       if (!strcmp(cp,"all")) continue;
  955.       do {
  956.     nrofallowedstr++;
  957.     if ((next=strchr(cp, ','))!=NULL)
  958.       *(next++) = '\0';
  959.     tmp = (linked_char*) malloc(sizeof(linked_char));
  960.     tmp->name = add_string(cp);
  961.     tmp->next = art->allowed;
  962.     art->allowed = tmp;
  963.       } while ((cp=next)!=NULL);
  964.     }
  965.     else if (sscanf(cp, "chance %d", &value))
  966.     art->chance = (uint16) value;
  967.     else if (sscanf(cp, "difficulty %d", &value))
  968.     art->difficulty = (uint8) value;
  969.     else if (!strncmp(cp, "Object",6)) {
  970.     art->item = (object *) malloc(sizeof(object));
  971.     reset_object(art->item);
  972.         if (!load_object(fp, art->item))
  973.        LOG(llevError,"Init_Artifacts: Could not load object.\n");
  974.     art->item->name = add_string((strchr(cp, ' ')+1));
  975.     al=find_artifactlist(art->item->type);
  976.     if (al==NULL) {
  977.       al = get_empty_artifactlist();
  978.       al->type = art->item->type;
  979.       al->next = first_artifactlist;
  980.       first_artifactlist = al;
  981.     }
  982.     art->next = al->items;
  983.     al->items = art;
  984.     }
  985.     else
  986.     LOG(llevError,"Unkown input in artifact file: %s\n", buf);
  987.   }
  988.  
  989.   close_and_delete(fp, comp);
  990.  
  991.   for (al=first_artifactlist; al!=NULL; al=al->next) {
  992.     for (art=al->items; art!=NULL; art=art->next) {
  993.       if (!art->chance)
  994.     LOG(llevError,"Warning: artifact with no chance: %s\n", art->item->name);
  995.       else
  996.     al->total_chance += art->chance;
  997.     }
  998. #if 0
  999.     LOG(llevDebug,"Artifact list type %d has %d total chance\n",
  1000.     al->type, al->total_chance);
  1001. #endif
  1002.   }
  1003.  
  1004. #ifdef DUMP_SWITCHES
  1005.   if (dump_monsters == 3) {
  1006.     dump_artifacts();
  1007.     exit(0);
  1008.   }
  1009. #endif
  1010. }
  1011.  
  1012.  
  1013. /*
  1014.  * Used in artifact generation.  The bonuses of the first object
  1015.  * is modified by the bonuses of the second object.
  1016.  */
  1017.  
  1018. void add_abilities(object *op, object *change) {
  1019.   int i, tmp;
  1020.   if (change->face != blank_face) {
  1021.     LOG(llevDebug, "FACE: %d\n", change->face->number);
  1022.     op->face = change->face;
  1023.   }
  1024.   for (i = 0; i < 7; i++)
  1025.     change_attr_value(&(op->stats), i, get_attr_value(&(change->stats), i));
  1026.   if (QUERY_FLAG(change,FLAG_CURSED))
  1027.     SET_FLAG(op, FLAG_CURSED);
  1028.   if (QUERY_FLAG(change,FLAG_DAMNED))
  1029.     SET_FLAG(op, FLAG_DAMNED);
  1030.   if ((QUERY_FLAG(change,FLAG_CURSED) || QUERY_FLAG(change,FLAG_DAMNED))
  1031.      && op->magic > 0)
  1032.     set_abs_magic(op, -op->magic);
  1033.   op->immune |= change->immune;
  1034.   op->protected |= change->protected;
  1035.   op->attacktype |= change->attacktype;
  1036.   op->vulnerable |= change->vulnerable;
  1037.   op->path_attuned |= change->path_attuned;
  1038.   op->path_repelled |= change->path_repelled;
  1039.   op->path_denied |= change->path_denied;
  1040.   op->stats.luck += change->stats.luck;
  1041.   if (QUERY_FLAG(change,FLAG_LIFESAVE))
  1042.     SET_FLAG(op,FLAG_LIFESAVE);
  1043.   if (QUERY_FLAG(change,FLAG_REFL_SPELL))
  1044.     SET_FLAG(op,FLAG_REFL_SPELL);
  1045.   if (QUERY_FLAG(change,FLAG_STEALTH))
  1046.     SET_FLAG(op,FLAG_STEALTH);
  1047.   if (QUERY_FLAG(change,FLAG_FLYING))
  1048.     SET_FLAG(op,FLAG_FLYING);
  1049.   if (QUERY_FLAG(change,FLAG_XRAYS))
  1050.     SET_FLAG(op,FLAG_XRAYS);
  1051.   if (QUERY_FLAG(change,FLAG_BLIND))
  1052.     SET_FLAG(op,FLAG_BLIND);
  1053. #ifdef USE_LIGHTING
  1054.   if (QUERY_FLAG(change,FLAG_SEE_IN_DARK))
  1055.     SET_FLAG(op,FLAG_SEE_IN_DARK);
  1056. #endif
  1057.   if (QUERY_FLAG(change,FLAG_REFL_MISSILE))
  1058.     SET_FLAG(op,FLAG_REFL_MISSILE);
  1059.   if (QUERY_FLAG(change,FLAG_MAKE_INVIS))
  1060.     SET_FLAG(op,FLAG_MAKE_INVIS);    
  1061.   if (QUERY_FLAG(change,FLAG_STAND_STILL)) {
  1062.     CLEAR_FLAG(op,FLAG_ANIMATE);
  1063.     op->speed = 0.0;
  1064.     update_ob_speed(op);
  1065.   }
  1066.   if(change->nrof) op->nrof=RANDOM()%((int) change->nrof) + 1;
  1067.   op->stats.exp += change->stats.exp; /* Speed modifier */
  1068.   op->stats.wc  += change->stats.wc;
  1069.   op->stats.ac  += change->stats.ac;
  1070.   if (change->stats.hp < 0)
  1071.      op->stats.hp = -change->stats.hp;
  1072.   else 
  1073.     op->stats.hp  += change->stats.hp;
  1074.   if (change->stats.maxhp < 0)
  1075.     op->stats.maxhp = -change->stats.maxhp;
  1076.   else
  1077.     op->stats.maxhp += change->stats.maxhp;
  1078.   if (change->stats.sp < 0)
  1079.     op->stats.sp = -change->stats.sp;
  1080.   else
  1081.     op->stats.sp  += change->stats.sp;
  1082.   if (change->stats.maxsp < 0)
  1083.     op->stats.maxsp = -change->stats.maxsp;
  1084.   else
  1085.     op->stats.maxsp  += change->stats.maxsp;
  1086.   if (change->stats.food < 0)
  1087.     op->stats.food = -(change->stats.food);
  1088.   else
  1089.     op->stats.food += change->stats.food;
  1090.   if (change->level < 0)
  1091.     op->level = -(change->level);
  1092.   else
  1093.     op->level += change->level;
  1094.   if (change->armour)
  1095.     if (change->armour < 0)
  1096.       op->armour = (-change->armour);
  1097.     else
  1098.       op->armour  = (signed char) (((int)op->armour * (int)change->armour)/10);
  1099.   if (change->stats.dam)
  1100.     if (change->stats.dam < 0)
  1101.       op->stats.dam = (-change->stats.dam);
  1102.     else if (op->stats.dam) {
  1103.       tmp = (signed char) (((int)op->stats.dam * (int)change->stats.dam)/10);
  1104.       if (tmp == op->stats.dam)
  1105.         if (change->stats.dam < 10)
  1106.           op->stats.dam--;
  1107.         else
  1108.           op->stats.dam++;
  1109.       else
  1110.         op->stats.dam = tmp;
  1111.     }
  1112.   if (change->weight)
  1113.     if (change->weight < 0)
  1114.       op->weight = (-change->weight);
  1115.     else
  1116.       op->weight = (op->weight    * (change->weight)) / 100;
  1117.   if (change->last_sp)
  1118.     if (change->last_sp < 0)
  1119.       op->last_sp = (-change->last_sp);
  1120.     else
  1121.       op->last_sp = (signed char) (((int)op->last_sp * (int)change->last_sp) / (int) 100);
  1122.   if (change->last_heal)
  1123.     if (change->last_heal < 0)
  1124.       op->last_heal = (-change->last_heal);
  1125.     else
  1126.       op->last_heal = (signed char) (((int)op->last_heal * ((int)change->last_heal))
  1127.                       / (int)100);
  1128.   op->value *= change->value;
  1129.  
  1130.   if(change->material)  op->material = change->material;
  1131.  
  1132.   if (change->slaying) {
  1133.     if (op->slaying)
  1134.       free_string(op->slaying);
  1135.     op->slaying = add_refcount(change->slaying);
  1136.   }
  1137.   if (change->race) {
  1138.     if (op->race)
  1139.       free_string(op->race);
  1140.     op->race = add_refcount(change->race);
  1141.   }
  1142.   if (change->msg) {
  1143.     if (op->msg)
  1144.       free_string(op->msg);
  1145.     op->msg = add_refcount(change->msg);
  1146.   }
  1147. }
  1148.  
  1149. static int legal_artifact_combination(object *op, artifact *art) {
  1150.   int neg, success = 0;
  1151.   linked_char *tmp;
  1152.   char *name;
  1153.  
  1154.   if (art->allowed == (linked_char *) NULL)
  1155.     return 1; /* Ie, "all" */
  1156.   for (tmp = art->allowed; tmp; tmp = tmp->next) {
  1157.     LOG(llevDebug, "legal_art: %s\n", tmp->name);
  1158.     if (*tmp->name == '!')
  1159.       name = tmp->name + 1, neg = 1;
  1160.     else
  1161.       name = tmp->name, neg = 0;
  1162.  
  1163.     /* If we match name, then return the opposite of 'neg' */
  1164.     if (!strcmp(name,op->name) || (op->arch && !strcmp(name,op->arch->name)))
  1165.       return !neg;
  1166.  
  1167.     /* Set success as true, since if the match was an inverse, it means
  1168.      * everything is allowed except what we match
  1169.      */
  1170.     else if (neg)
  1171.       success = 1;
  1172.   }
  1173.   return success;
  1174. }
  1175.  
  1176. /*
  1177.  * Fixes the given object, giving it the abilities and titles
  1178.  * it should have due to the second artifact-template.
  1179.  */
  1180.  
  1181. void give_artifact_abilities(object *op, object *artifct) {
  1182.   char new_name[MAX_BUF], identified;
  1183.  
  1184.   sprintf(new_name, "of %s", artifct->name);
  1185.   if (op->title)
  1186.     free_string(op->title);
  1187.   op->title = add_string(new_name);
  1188.   add_abilities(op, artifct); /* Give out the bonuses */
  1189.  
  1190. #if 1 /* Bit verbose, but keep it here until next time I need it... */
  1191.   identified = QUERY_FLAG(op, FLAG_IDENTIFIED);
  1192.   SET_FLAG(op, FLAG_IDENTIFIED);
  1193.   LOG(llevDebug, "Generated artifact %s %s [%s]\n",
  1194.       op->name, op->title, describe_item(op));
  1195.   if (!identified)
  1196.       CLEAR_FLAG(op, FLAG_IDENTIFIED);
  1197. #endif
  1198.   return;
  1199. }
  1200.  
  1201. /*
  1202.  * Decides randomly which artifact the object should be
  1203.  * turned into.  Makes sure that the item can become that
  1204.  * artifact (means magic, difficulty, and Allowed fields properly).
  1205.  * Then calls give_artifact_abilities in order to actually create
  1206.  * the artifact.
  1207.  */
  1208.  
  1209. /* Give 1 re-roll attempt per artifact */
  1210. #define ARTIFACT_TRIES 2
  1211.  
  1212. void generate_artifact(object *op, int difficulty) {
  1213.   artifactlist *al;
  1214.   artifact *art;
  1215.   int i;
  1216.  
  1217.   al = find_artifactlist(op->type);
  1218.   
  1219.   if (al==NULL) {
  1220. #if 0 /* This is too verbose, usually */
  1221.     LOG(llevDebug, "Couldn't change %s into artifact - no table.\n", op->name);
  1222. #endif
  1223.     return;
  1224.   }
  1225.  
  1226.   for (i = 0; i < ARTIFACT_TRIES; i++) {
  1227.     int roll = RANDOM()% al->total_chance;
  1228.  
  1229.     for (art=al->items; art!=NULL; art=art->next) {
  1230.       roll -= art->chance;
  1231.       if (roll<0) break;
  1232.     }
  1233.     
  1234.     if (art == NULL || roll>=0) {
  1235. #if 1
  1236.       LOG(llevError, "Got null entry and non zero roll in generate_artifact, type %d\n",
  1237.     op->type);
  1238. #endif
  1239.       return;
  1240.     }
  1241.     if (!strcmp(art->item->name,"NONE")) 
  1242.     return;
  1243.     if (FABS(op->magic) < art->item->magic)
  1244.       continue; /* Not magic enough to be this item */
  1245.  
  1246.     /* Map difficulty not high enough */
  1247.     if (difficulty<art->difficulty)
  1248.     continue;
  1249.  
  1250.     if (!legal_artifact_combination(op, art)) {
  1251.       LOG(llevDebug, "%s of %s was not a legal combination.\n",
  1252.           op->name, art->item->name);
  1253.       continue;
  1254.     }
  1255.     give_artifact_abilities(op, art->item);
  1256.     return;
  1257.   }
  1258. }
  1259.  
  1260.  
  1261.